<?php
declare (strict_types = 1);

namespace app\command;

use app\model\Device;
use app\model\DeviceRecords;
use Stomp\Client;
use Stomp\Exception\StompException;
use Stomp\Network\Observer\Exception\HeartbeatException;
use Stomp\Network\Observer\ServerAliveObserver;
use Stomp\StatefulStomp;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
use think\facade\Log;
class Amqp extends Command
{
    protected function configure()
    {
        // 指令配置
        $this->setName('amqps')
            ->setDescription('the amqps command');
    }

    protected function execute(Input $input, Output $output)
    {
       $r =  file_put_contents('amqp.txt',3123);

//        $output->writeln('amqps');
//        $output->writeln((string)$r);
//
//        die;

        //参数说明，请参见AMQP客户端接入说明文档。
        $accessKey = "LTAI5t8fu2Bed5aT5R9pqyku";
        $accessSecret = "rxwE7p8OSlp8k0c94FxEek0VEG7WqY";
        $consumerGroupId = "DEFAULT_GROUP";
        $clientId = 996;
//iotInstanceId：实例ID。
        $iotInstanceId = "iot-06z00eflfgjdvpq";
        $timeStamp = round(microtime(true) * 1000);
//签名方法：支持hmacmd5，hmacsha1和hmacsha256。
        $signMethod = "hmacsha1";
//userName组装方法，请参见AMQP客户端接入说明文档。
//若使用二进制传输，则userName需要添加encode=base64参数，服务端会将消息体base64编码后再推送。具体添加方法请参见下一章节“二进制消息体说明”。
        $userName = $clientId . "|authMode=aksign"
            . ",signMethod=" . $signMethod
            . ",timestamp=" . $timeStamp
            . ",authId=" . $accessKey
            . ",iotInstanceId=" . $iotInstanceId
            . ",consumerGroupId=" . $consumerGroupId
            . "|";
        $signContent = "authId=" . $accessKey . "&timestamp=" . $timeStamp;
//计算签名，password组装方法，请参见AMQP客户端接入说明文档。
        $password = base64_encode(hash_hmac("sha1", $signContent, $accessSecret, $raw_output = TRUE));
//接入域名，请参见AMQP客户端接入说明文档。
        $client = new Client('ssl://iot-06z00eflfgjdvpq.amqp.iothub.aliyuncs.com:61614');

        $sslContext = ['ssl' => ['verify_peer' => true, 'verify_peer_name' => false], ];
        $client->getConnection()->setContext($sslContext);

//服务端心跳监听。
        $observer = new ServerAliveObserver();
        $client->getConnection()->getObservers()->addObserver($observer);
        //心跳设置，需要云端每30s发送一次心跳包。
        $client->setHeartbeat(0, 30000);
        $client->setLogin($userName, $password);

        try {
            $client->connect();

        }
        catch(StompException $e) {
            echo "failed to connect to server, msg:" . $e->getMessage() , PHP_EOL;
        }
//无异常时继续执行。
        $stomp = new StatefulStomp($client);
        $stomp->subscribe('/topic/#');
//        return $stomp->read();die;
        while (true) {
            try {

                // 检查连接状态
                if (!$client->isConnected()) {
                    echo "connection not exists, will reconnect after 10s.", PHP_EOL;
                    sleep(10);
                    $client->connect();
                    $stomp->subscribe('/topic/#');
                    echo "connect success", PHP_EOL;
                }
//                dump($stomp->read());
//                $read = $stomp->read();

                //处理消息业务逻辑。
                $ret= $stomp->read();
                $getHeaders = $ret->getHeaders();
                $topic = $getHeaders['topic'];
                $device_name = explode('/',$topic)[2];
                $con = $ret->getBody();



                $status = [
                    'Openn'=>'开机',
                    'Close'=>'关机',
                    'Pause'=>'暂停',
                    'BalON'=>'平衡(开)',
                    'BaOFF'=>'平衡(关)',
                    'OvlON'=>'超载(开)',
                    'OvOFF'=>'超载(关)',
                    'BalanceFault01'=>'平衡故障',
                    'LimitFault02'=>'限位故障',
                    'OverloadFault03'=>'超载故障',

                    'MotorFault04' =>'电机故障',
                    'HangUpFault05' => '挂断故障'
                    ];
                $content = '默认:'.$con; //修改最后一条的数据

//                $id = Device::where('title',$device_name)->value('id');
//                $BalanceFault01 = Device::where('title',$device_name)->value('BalanceFault01');
//                $LimitFault02 = Device::where('title',$device_name)->value('LimitFault02');
//                $OverloadFaut03 = Device::where('title',$device_name)->value('OverloadFaut03');
//                $MotorFault04 = Device::where('title',$device_name)->value('MotorFault04');
//                $HangUpFault05 = Device::where('title',$device_name)->value('HangUpFault05');

                $is_insert = false;
//                if (in_array($con, ['BalON', 'BalOFF'])) {
//                    $content = $status[$con];
//                    $is_insert = true;
//                    Device::where('id',$id)->update(['balance'=>$content]);
//                }
//                if (in_array($con, [ 'OvON', 'OvOFF'])) {
//                    $content = $status[$con];
//                    $is_insert = true;
//                    Device::where('id',$id)->update(['overload'=>$content]);
//                }
                if(is_numeric($con)){
                    Device::where('title',$device_name)->update(['runtime'=>$con]);
                    $content = $con;
                }
                if (in_array($con, ['Openn', 'Close', 'Pause'])) {
                    $content = $status[$con];
                    $is_insert = true;
                    $device = Device::where('title',$device_name)->select();
                    if(!$device->isEmpty()) {
                        foreach ($device as $v) {
                            $v->save(['remote_status' => $content]);
                        }
                    }
                }
                if (in_array($con, ['BalON','BaOFF'])) {
                    $content = $status[$con];
                    $is_insert = true;
                    $device = Device::where('title',$device_name)->select();
                    $swtich = ['BalON'=>1,'BaOFF'=>2];
                    if(!$device->isEmpty()) {
                        foreach ($device as $v) {
//                            $v->save(['balance' => $swtich[$con]]);
                            $v->save(['balance' =>$content]);
                        }
                    }
                }
                if (in_array($con, ['OvlON','OvOFF'])) {
                    $content = $status[$con];
                    $is_insert = true;
                    $device = Device::where('title',$device_name)->select();
                    $swtich = ['OvlON'=>1,'OvOFF'=>2];
                    if(!$device->isEmpty()) {
                        foreach ($device as $v) {
                            //$v->save(['over_switch' => $swtich[$con]]);
                            $v->save(['overload' =>$content]);
                        }
                    }
                }
                //平衡
                if (in_array($con, ['BalanceFault01'])) {
                    $content = $status[$con];
                    $is_insert = true;
                    $device = Device::where('title',$device_name)->select();
                    if(!$device->isEmpty()) {
                        foreach ($device as $v) {
                            if ($v['BalanceFault01'] == 1) {
                                $v->save(['error' => $content]);
                            }
                        }
                    }
                }
                //限位
                if (in_array($con, ['LimitFault02'])) {
                    $content = $status[$con];
                    $is_insert = true;
                    $device = Device::where('title',$device_name)->select();
                    if(!$device->isEmpty()) {
                        foreach ($device as $v) {
                            if ($v['LimitFault02'] == 1) {
                                $v->save(['error' => $content]);
                            }
                        }
                    }
                }
                //过载
                if (in_array($con, ['OverloadFault03'])) {
                    $content = $status[$con];
                    $is_insert = true;
                    $device = Device::where('title',$device_name)->select();
                    if(!$device->isEmpty()){
                        foreach ($device as $v){
                            if($v['OverloadFault03'] == 1){
                                $v->save(['error'=>$content]);
                            }
                        }
                    }

                }
                    //点击
                if (in_array($con, ['MotorFault04'])) {
                    $content = $status[$con];
                    $is_insert = true;
                    $device = Device::where('title',$device_name)->select();
                    if(!$device->isEmpty()) {
                        foreach ($device as $v) {
                            if ($v['MotorFault04'] == 1) {
                                $v->save(['error' => $content]);
                            }
                        }
                    }
                }
                //挂断故障
                if (in_array($con, ['HangUpFault05'])) {
                    $content = $status[$con];
                    $is_insert = true;
                    $device = Device::where('title',$device_name)->select();
                    if(!$device->isEmpty()) {
                        foreach ($device as $v) {
                            if ($v['HangUpFault05'] == 1) {
                                $v->update(['error' => $content]);
                            }
                        }
                    }
                }
                if (in_array($con, ['clear'])) {
//                    $content = $status[$con];
                    $is_insert = true;
                    $device = Device::where('title',$device_name)->select();
                    if(!$device->isEmpty()) {
                        foreach ($device as $v) {

                                $v->update(['error' => '']);

                        }
                    }
                }

                DeviceRecords::create([
                    "qos" => $getHeaders['qos'],
                    "destination" => $getHeaders['destination'],
                    "message_id" => $getHeaders['message-id'],
                    "topic" => $getHeaders['topic'],
                    "subscription" => $getHeaders['subscription'],
                    "generateTime" => $getHeaders['generateTime'],
                    "device_name" => $device_name,
                    "content" => $content
                ]);
//                DeviceRecords::table('records')->insert([
//                    "qos" => $ret->getHeaders()['qos'],
//                    "destination" => $ret->getHeaders()['destination'],
//                    "message_id" => $ret->getHeaders()['message-id'],
//                    "topic" => $ret->getHeaders()['topic'],
//                    "subscription" => $ret->getHeaders()['subscription'],
//                    "generateTime" => $ret->getHeaders()['generateTime'],
//                    "device_name" => $device_name,
//                    "content" =>$content,
//                    "create_time" => date('Y-m-d H:i:s')
//                ]);

                //writeLog('amqp');
                //Db::name('aa')->insert(['num'=>$stomp->read()->getBody(),'part_number'=>1]);

            }
            catch(HeartbeatException $e) {
                echo 'The server failed to send us heartbeats within the defined interval.', PHP_EOL;
                $stomp->getClient()->disconnect();
            } catch(\Exception $e) {
                writeLog($e->getMessage());
                echo 'process message occurs error: '. $e->getMessage() , PHP_EOL;
                $stomp->getClient()->disconnect();
            }
        }
    }
}
